package com.scujj.cs6.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.scujj.cs6.model.entity.WeatherForecast;
import com.scujj.cs6.model.dto.WeatherForecastDTO;
import com.scujj.cs6.service.WeatherForecastService;
import com.scujj.cs6.service.WeatherService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;

@Slf4j
@Component
@RequiredArgsConstructor
public class WeatherForecastsScheduleJob {

    private final WeatherService weatherService;

    private final ThreadPoolTaskExecutor taskExecutor;

    private final WeatherForecastService weatherForecastService;

    /**
     * 每天0点和12点同步天气预报数据
     */
    @Scheduled(cron = "0 0 0,12 * * ?")
    public void syncForecastData() {
        List<WeatherForecastDTO> forecastDTOS = weatherService.fetchCapitalCitiesForecasts();
        int total = forecastDTOS.size();
        Semaphore semaphore = new Semaphore(5); // 限制并发数为5
        CountDownLatch latch = new CountDownLatch(total); // 等待所有任务完成

        for (WeatherForecastDTO forecastDTO : forecastDTOS) {
            taskExecutor.execute(() -> {
                try {
                    semaphore.acquire();
                    List<WeatherForecast> existData = weatherForecastService.list(new LambdaQueryWrapper<>(WeatherForecast.class)
                            .eq(WeatherForecast::getAdcode, forecastDTO.getAdcode())
                            .orderByDesc(WeatherForecast::getDate)
                            .last("LIMIT 5")
                    );
                    List<WeatherForecast> forecasts = new ArrayList<>(forecastDTO.getForecasts().stream().map((item) -> {
                        WeatherForecast wf = new WeatherForecast(item);
                        wf.setAdcode(forecastDTO.getAdcode());
                        return wf;
                    }).toList());

                    if (existData != null && !existData.isEmpty()) {
                        forecasts.removeIf(forecast -> existData.stream()
                                .anyMatch(existing -> existing.getDate().equals(forecast.getDate())));
                    }

                    weatherForecastService.saveBatch(forecasts);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    semaphore.release();
                    latch.countDown(); // 任务完成，计数器减一
                }
            });
        }

        try {
            latch.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

}